﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Serialization;
using AutoTest.Common.Extension;
using EasyTool;

namespace AutoTest.Common.UtilsHelper
{
    /// <summary>
    /// 
    /// </summary>
    public class XmlHelper
    {
        /// <summary>
        /// 转成Json
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="ignoreNullOrEmpty"></param>
        /// <returns></returns>
        public static string ToXml<T>(T? obj, bool ignoreNullOrEmpty)
        {
            Dictionary<string, object> dict = obj?.ToDictionary()??[];
            return ToXml(dict, ignoreNullOrEmpty);
        }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToXml(Dictionary<string, object> dict, bool ignoreNullOrEmpty)
        {
            //数据为空时不能转化为xml格式
            if (0 == dict.Count)
            {
                return "";
            }

            string xml = "<xml>";
            foreach (KeyValuePair<string, object> pair in dict)
            {
                //字段值不能为null，会影响后续流程
                if ((pair.Value.IsNull() || (pair.Value?.ToString() ?? "").IsEmpty()) && ignoreNullOrEmpty)
                {
                    continue;
                }

                if (pair.Value?.GetType() == typeof(int))
                {
                    xml += "<" + pair.Key + ">" + pair.Value + "</" + pair.Key + ">";
                }
                else if (pair.Value?.GetType() == typeof(string))
                {
                    xml += "<" + pair.Key + ">" + "<![CDATA[" + pair.Value + "]]></" + pair.Key + ">";
                }
                else if (pair.Value?.GetType() == typeof(DateTime))
                {
                    xml += "<" + pair.Key + ">" + TimestampUtil.ConvertToTimestamp((DateTime)pair.Value) + "</" + pair.Key + ">";
                }
                else//除了string和int类型不能含有其他数据类型
                {
                    xml += "<" + pair.Key + ">" + "<![CDATA[" + (pair.Value?.ToString() ?? "") + "]]></" + pair.Key + ">";
                }
            }
            xml += "</xml>";
            return xml;
        }

        public static Dictionary<string, string> FromXml(string xml)
        {
            var dict = new Dictionary<string, string>();
            var xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xml);
            var xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
            var nodes = xmlNode?.ChildNodes;
            if (nodes != null)
            {
                foreach (XmlNode xn in nodes)
                {
                    XmlElement xe = (XmlElement)xn;
                    dict[xe.Name.Trim()] = xe.InnerText.Trim();
                }
            }

            return dict;
        }

        public static T DeserializeXml<T>(string xml)
        {
            T obj = Activator.CreateInstance<T>();
            var dict = new Dictionary<string, string>();
            obj = DeserializeDictionary<T>(dict);
            return obj;
        }

        public static T DeserializeDictionary<T>(Dictionary<string, string> dict)
        {
            T obj = Activator.CreateInstance<T>();
            PropertyInfo[] properties = typeof(T).GetProperties();
            foreach (var property in properties)
            {
                string name = property.Name;
                object? v = null;
                if (dict.TryGetValue(name, out string? value))
                {
                    string dictValue = value;
                    if (property.PropertyType.IsPrimitive)
                    {
                        v = Convert.ChangeType(dictValue, property.PropertyType);
                    }
                    else
                    {
                        v = dictValue;
                    }

                    property.SetValue(obj, v);
                }
            }

            return obj;
        }
    }
}
